package club.itstudio.itouc.entity

import club.itstudio.itouc.core.exception.ConnectFailure
import club.itstudio.itouc.core.util.SpringContext
import club.itstudio.itouc.core.util.nextStr
import club.itstudio.itouc.jw.JwHost
import club.itstudio.itouc.jw.ParamsBuilder
import club.itstudio.itouc.jw.with
import club.itstudio.itouc.service.JwOps
import club.itstudio.itouc.util.Bean
import club.itstudio.itouc.util.Redis
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
import com.github.kittinunf.fuel.Fuel
import com.github.kittinunf.result.Result
import kotlin.random.Random

/**
 * 教务系统会话
 */
@JsonIgnoreProperties("token")
data class JwSession(
        var userCode: String,                               // 学号
        var password: String,                               // 密码
        var jsessionid: String = getJwSessionId(),          // cookie
        var timestamp: Long = System.currentTimeMillis(),   // 标志着会话创建或更新的时间
        @JsonIgnore
        var token: String = Random.nextStr(28)        // 令牌，发给用户，服务器不保存
) {
    override fun toString(): String {
        return "JSESSIONID=$jsessionid"
    }

    /**
     * 保存到redis
     */
    fun save() = Bean.redis().saveJwSession(this)

    /**
     * 从redis中删除
     */
    fun delete() = Bean.redis().deleteJwSession(token)

    /**
     * 验证有效性
     */
    private fun valid(): Boolean{
        // 若为首次创建
        if (timestamp == -1L) return false

//        // 若更新时间少于15分钟
//        val last = System.currentTimeMillis() - this.timestamp
//        if (last < 15 * 60 * 1000) return true

        // 否则向教务系统验证
        val jw = SpringContext.getBean(ParamsBuilder::class.java)
        val data = jw.onlineMessage() with this
        return data == "<xml id='OnlineMessageList'></xml>"
    }

    /**
     * 刷新会话
     */
    fun refresh() {
        if (!valid()) {
            // 重新获取session
            this.jsessionid = getJwSessionId()
            SpringContext.getBean(JwOps::class.java).loginJw(this)
        }
        // 更新时间戳
        this.timestamp = System.currentTimeMillis()
        this.save()
    }

}


/**
 * 获取新的会话ID
 */
fun getJwSessionId(): String {
    val (_, response, result) = Fuel.get(JwHost).response()
    return  when(result) {
        is Result.Failure -> throw ConnectFailure()
        is Result.Success -> response
                .header("Set-Cookie")
                .first()
                .substring(11, 49)
    }
}
